package ru.compscicenter.uno.view;

import ru.compscicenter.uno.actor.Actor;
import ru.compscicenter.uno.controller.AController;
import ru.compscicenter.uno.log.Logger;
import ru.compscicenter.uno.model.*;
import sun.rmi.runtime.Log;

public class ConsoleViewer implements View {
	private final AController controller;
	private int myPlayerId = 0;
    Actor actor;

	private static final String DROP = "drop "; //<card id>
	private static final String COLOR_BLUE = "blue";
	private static final String COLOR_GREEN = "green";
	private static final String COLOR_RED = "red";
	private static final String COLOR_YELLOW = "yellow";
	private static final String TAKE = "take";
	private static final String SAY_UNO = "uno!";
	private static final String DIDNT_SAY_UNO = "achtung "; //<player id>
	private static final String END_TURN = "end turn";

	private static final String ADD_PLAYER = "add player "; //<name>
	private static final String DELETE_PLAYER = "delete player "; //<id>
	private static final String START_GAME = "start game";
	private static final String START_ROUND = "start round";
    private static final String CLIENT_ROUND_ENDED = "client_round_ended";

	private static final String QUIT = "quit";

	public ConsoleViewer(AController c, Actor actor) {
		this.controller = c;
        c.getModel().setView(this);
        this.actor = actor;
        while (!c.isReady) {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        Thread updater = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    if (controller.isChanged()) {
                        printGameState();
                        System.out.println("To go: " + controller.getCurrentPlayerId());
                        System.out.print('>');
                        controller.setIsChanged(false);
                    }
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        updater.setDaemon(true);
        updater.start();
	}

	public void run() {
        myPlayerId = controller.getMyPlayerId();
		while (true) {
			//HACKED!! emulating queue of players in one console

			if (controller.isChanged()) {
                if (controller.isGameRunning()) {
                    //print all info
                    //printGameState();
                    //System.out.println("To go: " + controller.getCurrentPlayerId());
                    //System.out.print('>');
                }
            }

			if (controller.isRoundEnded()) {
				System.out.println("Game ended");
				//print players state
				printPlayersState();
				System.out.println("Winner: " + controller.getPlayer(controller.getRoundWinnerPlayerId()));
                try {
                    controller.startRound();
                } catch (ModelException e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                }
                
                String str = "";
                for (Player player : controller.getPlayers()) {
                    int points = player.getPoints();
                    str += points + " ";
                }
                Logger.write("***** ROUND ENDED *****\nPOINTS: " + str, Logger.Mode.ACTION);
            }

            if (controller.isGameEnded()) {
                System.out.println("Game ended");
                //print players state
                String str = "";
                for (Player player : controller.getPlayers()) {
                    int points = player.getPoints();
                    str += points + " ";
                }
                Logger.write("***** GAME ENDED *****\nPOINTS: " + str, Logger.Mode.ACTION);
                printPlayersState();
                System.out.println("Winner: " + controller.getPlayer(controller.getGameWinnerPlayerId()));
            }


            while (myPlayerId != controller.getCurrentPlayerId()) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    System.exit(1);
                }
            }


			String input = actor.getAction();
            //System.out.println("\n ********************** ACTION = " + input + " **********************\n");

			try {
				boolean success = false;
				if (QUIT.equals(input)) {
					break;
				} else if (input.startsWith(DROP)) {
					int cardId = Integer.parseInt(input.substring(DROP.length()));
					if (controller.getPlayer(myPlayerId).getCard(cardId).getColor() == Card.Color.ANY) {
						System.out.println("color: ");
						String colorStr = actor.getColor();
                        System.out.println("In COLOR =" + colorStr + "!");
						Card.Color color;
						if (COLOR_BLUE.equals(colorStr)) {
							color = Card.Color.BLUE;
						} else if (COLOR_GREEN.equals(colorStr)) {
							color = Card.Color.GREEN;
						} else if (COLOR_RED.equals(colorStr)) {
							color = Card.Color.RED;
						} else if (COLOR_YELLOW.equals(colorStr)) {
							color = Card.Color.YELLOW;
						} else {
							System.out.println("invalid color");
							continue;
						}
						success = controller.doDropCard(myPlayerId, cardId, color);
					} else {
						success = controller.doDropCard(myPlayerId, cardId);
					}
                    if (success) {
                        actor.setDroppedCard(true);
                    }
				} else if (input.startsWith(TAKE)) {
					success = controller.doTakeCard(myPlayerId);
				} else if (input.startsWith(SAY_UNO)) {
					success = controller.doSayUno(myPlayerId);
				} else if (input.startsWith(DIDNT_SAY_UNO)) {
					int whoDidntSaidUnoId = Integer.parseInt(input.substring(DIDNT_SAY_UNO.length()));
					success = controller.doSomebodyDidntSayUno(myPlayerId, whoDidntSaidUnoId);
				} else if (input.startsWith(END_TURN)) {
					success = controller.doEndTurn(myPlayerId);
				} else if (input.startsWith(ADD_PLAYER)) {
					String name = input.substring(ADD_PLAYER.length());
					Player player = new Player(name);
					success = controller.addPlayer(player);
				} else if (input.startsWith(DELETE_PLAYER)) {
					int playerId = Integer.parseInt(input.substring(DELETE_PLAYER.length()));
					success = controller.removePlayer(playerId);
				} else if (input.startsWith(START_GAME)) {
					success = controller.startGame();
				} else if (input.startsWith(START_ROUND)) {
					success = controller.startRound();
				} else {
					System.err.println("Invalid input");
					continue;
				}
                //System.out.println("\n");
				//System.out.println((success ? "ok" : "unvailable operation") + '\n');
			} catch (Exception e) {
				System.err.println(e.getMessage());
			}
		}
	}

    @Override
    public void onDropCard(int playerId, int cardId) {
        System.out.println("player " + playerId + " dropped card " + cardId);
    }

    @Override
    public void onDropCard(int playerId, int cardId, Card.Color selectedColor) {
        System.out.println("player " + playerId + " dropped wild card " + cardId + " color = " + selectedColor);
    }

    @Override
    public void onTakeCard(int playerId) {
        System.out.println("player " + playerId + " took card");
    }

    @Override
    public void onSayUno(int playerId) {
        System.out.println("player " + playerId + " said uno");
    }

    @Override
    public void onSomebodyDidntSayUno(int playerId, int whoDidntSayUnoId) {
        System.out.println("player " + playerId + " think that player " + whoDidntSayUnoId + " didn't said uno");
    }

    @Override
    public void onEndTurn(int playerId) {
        System.out.println("player " + playerId + " end his turn");
    }

    public synchronized void printPlayersState() {
		System.out.println("Players:");
		for (Player player : controller.getPlayers()) {
			System.out.println(player);
		}
	}

	public synchronized void printGameState() {
		System.out.println("Game info:");
        System.out.println("Top card: " + controller.getTopCard() + " Top color: " + controller.getTopColor());

        for (Player player : controller.getPlayers()) {
			System.out.println(player);
		}
		Player me = controller.getPlayer(myPlayerId);
		//System.out.println("\nMe: " + me.getName() + "; id = " + me.getId() + "\nMy cards:");
		//for (Card card : me.getCards()) {
		//	System.out.println(card);
		//}
	}

}